#include "at_port.h"
#include "at_module.h"
#include "uart.h"
#include <string.h>
#include <stdio.h>
#include "timer.h"

#define AT_RECEIVE_BUFFER_LEN       1536   
static uint8_t          s_ATCmdReceiveBuffer[AT_RECEIVE_BUFFER_LEN];

static void ATUartInit(void)
{
    UartInit(UART_2,115200,s_ATCmdReceiveBuffer,AT_RECEIVE_BUFFER_LEN,100,0);
}
static void ATUartDeinit(void)
{
    UartDeinit(UART_2);
}

static int ATUartSend(const char* cmd,int len)
{
    UartSend(UART_2,(const uint8_t*)cmd,len);
    return 1;
}
static int ATUartRead(char* replyBuff,int maxLen)
{
    return UartRead(UART_2,1,(uint8_t*)replyBuff,maxLen);
}

static const ATPort    s_cATParserPort = 
{
    .fpUartInit = ATUartInit,
    .fpUartDeinit = ATUartDeinit,
    .fpUartSend = ATUartSend,
    .fpUartRead = ATUartRead,
    .cPrefix = "\r\n",
    .cSuffix = "\r\n",
};

//电源上/下电
static void ModulePowerOn(int flg)
{
    
}

//模块休眠
static void ModuleSleep(void)
{
    
}

//初始化指令
static const MODULE_ATCMD_CFG  s_ModuleInitCmd[] = 
{
    {
        .at_cmd = "AT\r\n",         //AT指令
        .at_len = sizeof("AT\r\n")-1,         //AT指令长度
        .at_will = "OK",        //希望收到的回复
        .timeout = 3000,        //超时时间
        .resendCnt = 10,      //重发次数
    },
    {
        .at_cmd = "ATE0\r\n",         //ATE0指令,关闭回显
        .at_len = sizeof("ATE0\r\n") - 1,         //AT指令长度
        .at_will = "OK",        //希望收到的回复
        .timeout = 3000,        //超时时间
        .resendCnt = 3,      //重发次数
    },
    {
        .at_cmd = "AT+CSQ\r\n",         //ATE0指令,关闭回显
        .at_len = sizeof("AT+CSQ\r\n")-1,         //AT指令长度
        .at_will = "OK",        //希望收到的回复
        .timeout = 3000,        //超时时间
        .resendCnt = 3,      //重发次数
    },
    {
        .at_cmd = "AT+CGREG?\r\n",         //查询GPRS连接状态
        .at_len = sizeof("AT+CGREG?\r\n")-1,         //AT指令长度
        .at_will = "+CGREG: 0,1",        //希望收到的回复
        .timeout = 3000,        //超时时间
        .resendCnt = 12,      //重发次数
    },
    
};

//查询IP地址
static int CheckIpCMD(const char buff[],int buffLen,char ip[])
{
    int context_state = 0;
    int context_id = 0;
    int context_type = 0;
    const char* tmp = strstr(buff,"+QIACT: 1");
    if(tmp)
    {
        int iNum = sscanf(tmp,"+QIACT: %d,%d",&context_id,&context_state);
        if(iNum == 2)
        {
            if(context_state)       //已激活，有IP
            {
                iNum = sscanf(tmp,"+QIACT: %d,%d,%d,\"%[^\"]",&context_id,&context_state,&context_type,ip);
                if(iNum == 4)
                    return strlen(ip);
            }
        }
    }
    return 0;
}
//获取IP地址
static int GetIpCMD(const char buff[],int buffLen,char ip[])
{
    //return CheckIpCMD(buff,buffLen,ip);
    return 1;
}

static const ATModuleIP     s_cATModuleIPPort = 
{
    .fpMakeCheckIp = CheckIpCMD,             
    .pcCheckIp = "AT+QIACT?\r\n",                 //查询IP的AT指令
    .pcCheckIpSuccess = "OK",                  //查询IP的AT指令成功
 
    .fpMakeGetIp = GetIpCMD,               
    .pcGetIp = "AT+QIACT=1\r\n",                   //请求获取IP的AT指令
    .pcGetIpSuccess = "OK",                    //请求获取IP的AT指令成功
    
    .iTimeOut = 30*1000,
};

void MakeTcpConnectCMD(int id,const char* ip,uint16_t port,char buff[],int buffLen)
{
    snprintf(buff,buffLen,"AT+QIOPEN=1,0,\"TCP\",\"%s\",%d,0,1\r\n",ip,port);
}
void MakeTcpDisconnectCMD(int id,char buff[],int buffLen)
{
    snprintf(buff,buffLen,"AT+QICLOSE=0\r\n");
}
void MakeTcpSendHeadCMD(int id,const uint8_t* pkt,int len,char buff[],int buffLen)
{
    snprintf(buff,buffLen,"AT+QISEND=0,%d\r\n",len);
}
void MakeTcpSendCMD(int id,const uint8_t* pkt,int len,char buff[],int buffLen)
{
    memcpy(buff,pkt,len);
    buff[len] = 0;
}


void ParserTcpReceiveCMD(int* id,const char* pkt,int pktLen,uint8_t* buff,int *len)
{
    const char *c_ucReceiveHead = strstr(pkt,"+QIURC: \"recv\"");
    if(c_ucReceiveHead)
    {
        int id = 0;
        int datalen = 0;
        int iNum = sscanf(c_ucReceiveHead,"+QIURC: \"recv\",%d,%d",&id,&datalen);
        if(iNum == 2)
        {
            const char* dataHead = strstr(c_ucReceiveHead,"\r\n");
            if(dataHead)
                dataHead += 2;
            memcpy(buff,dataHead,datalen);
            *len = datalen;
        }
    }
}

//初始化指令
static const MODULE_ATCMD_CFG  s_MqttConfigCmd[] = 
{
    {
        .at_cmd = "AT+QMTCFG=\"recv/mode\",0,0,1\r\n",         //AT指令
        .at_len = sizeof("AT+QMTCFG=\"recv/mode\",0,0,1\r\n") - 1,         //AT指令长度
        .at_will = "OK",        //希望收到的回复
        .timeout = 3000,        //超时时间
        .resendCnt = 3,      //重发次数
    },
};

static const ATModuleTCP    s_cATModuleTCPPort = 
{
    .fpMakeTcpConnect = MakeTcpConnectCMD,
    .fpMakeTcpDisconnect = MakeTcpDisconnectCMD,
    .fpMakeTcpSendHead = MakeTcpSendHeadCMD,
    .fpMakeTcpSend = MakeTcpSendCMD,
    .fpParserTcpReceive = ParserTcpReceiveCMD,
    .pcConnectSuccess = "+QIOPEN: 0,0",
    .pcSendHead = ">",
    .pcSendSuccess = "SEND OK",
    .pcDisconnectHead = "OK",
    .pcReceiveURC = "+QIURC: \"recv\"",
    .pcDisconnectURC = "+QIURC: \"closed\"",
    .iTimeout = 20*1000,
};

static uint16_t s_usMqttMsgID = 1;

//生成MQTT的TCP连接的AT指令
void MakeMqttTCPConnectCMD(const char* ip,uint16_t port,char buff[],int buffLen)
{
    snprintf(buff,buffLen,"AT+QMTOPEN=0,\"%s\",%d\r\n",ip,port);
}
//生成MQTT的连接AT指令
void MakeMqttConnectCMD(const char* clientid,const char* username,const char* password,char buff[],int buffLen)
{
    snprintf(buff,buffLen,"AT+QMTCONN=0,\"%s\",\"%s\",\"%s\"\r\n",clientid,username,password);
}
//生成MQTT的SUB AT指令
void MakeMqttSubCMD(const char* topic,int qos,char buff[],int buffLen)
{
    
    snprintf(buff,buffLen,"AT+QMTSUB=0,%d,\"%s\",%d\r\n",s_usMqttMsgID++,topic,qos);
}
//生成MQTT的PUB AT指令
void MakeMqttPubCMD(const char* topic,const char* payload,int payloadLen,int qos,char buff[],int buffLen)
{
    snprintf(buff,buffLen,"AT+QMTPUBEX=0,%d,%d,0,\"%s\",%d\r\n",s_usMqttMsgID,qos,topic,payloadLen);
}

//生成MQTT的PUB AT指令
void MakeMqttPubMessageCMD(const char* topic,const char* payload,int payloadLen,int qos,char buff[],int buffLen)
{
    memcpy(buff,payload,payloadLen);
    buff[payloadLen] = 0;
}

//生成MQTT的UNSUB AT指令
void MakeMqttUnSubCMD(const char* topic,int qos,char buff[],int buffLen)
{
    snprintf(buff,buffLen,"AT+QMTUNS=0,%d,\"%s\",%d\r\n",s_usMqttMsgID++,topic,qos);
}

//生成MQTT退出登录连接指令
void MakeMqttLogoutCMD(char buff[],int buffLen)
{
    snprintf(buff,buffLen,"AT+QMTCLOSE=0\r\n");
}


//生成MQTT主动断开连接指令
void MakeMqttDisconnectCMD(char buff[],int buffLen)
{
    snprintf(buff,buffLen,"AT+QMTDISC=0\r\n");
}

//生成MQTT接收PUB解析数据
void ParserMqttPubCMD(const char* pkt,int len,char* topic,char* payload,int *payloadLen,int *qos)
{
    const char* cmdHead = 0;
    cmdHead = strstr(pkt,"+QMTRECV");
    if(pkt)
    {
        int clientID = 0;
        int msgID = 0;
        
        sscanf(cmdHead,"+QMTRECV: %d,%d,\"%[^\"]\",\"%[^\"]",&clientID,&msgID,topic,payload);
    }
}

static const ATModuleMqtt   s_cATModuleMqttPort = 
{
    .pMqttConfig = s_MqttConfigCmd,
    .iMqttCfgCmdNum = sizeof(s_MqttConfigCmd)/sizeof(MODULE_ATCMD_CFG),
    .fpMakeMqttTcpConnect = MakeMqttTCPConnectCMD,
    .fpMakeMqttConncet = MakeMqttConnectCMD,
    .fpMakeMqttSub = MakeMqttSubCMD,
    .fpMakeMqttPub = MakeMqttPubCMD,
    .fpMakeMqttPubMessage = MakeMqttPubMessageCMD,
    .fpMakeMqttUnSub = MakeMqttUnSubCMD,
	.fpMakeMqttLogout = MakeMqttLogoutCMD,
    .fpMakeMqttDisconnect = MakeMqttDisconnectCMD,
    .fpParserMqttPub = ParserMqttPubCMD,
    
    .pcMqttConnectSuccess = "+QMTOPEN: 0,0", 
    .pcMqttLoginSuccess = "+QMTCONN: 0,0",
    .pcMqttPubHead = ">",
    .pcMqttPubSuccess = "+QMTPUBEX: 0",
    .pcMqttSubSuccess = "+QMTSUB: 0",/*,<msgID>,<result>*/
    .pcMqttUnsubSuccess = "+QMTUNS: 0",
    .pcMqttLogoutSuccess = "+QMTCLOSE: 0,0",
    .pcMqttDisconnectSuccess = "OK",
    
    .pcMqttPubURC = "+QMTRECV:",
    .pcMqttDisconnectURC = "+QMTSTAT: 0",
    
    .iTimeout = 20*1000,
};

ATModuleConfig      g_ATModule;

void ATModuleInit(pATGetSystick f)
{
    module_init(&g_ATModule);
    g_ATModule.pInitCmd = s_ModuleInitCmd;               //AT设备初始化的指令
    g_ATModule.iInitCmdNum = sizeof(s_ModuleInitCmd)/sizeof(MODULE_ATCMD_CFG);            //初始化指令个数
    g_ATModule.fpPowerOn = ModulePowerOn;              //模块上电
    g_ATModule.fpSleep = ModuleSleep;                //模块休眠
    g_ATModule.atConfig.atPort = &s_cATParserPort;               //
    g_ATModule.atConfig.fpSystick = f;
    g_ATModule.atIpCfg = &s_cATModuleIPPort;                //IP指令
    g_ATModule.atTcpCfg = &s_cATModuleTCPPort;               //TCP连接指令
    g_ATModule.atMqttCfg = &s_cATModuleMqttPort;              //MQTT连接指令
    
    at_parser_log(&g_ATModule.atConfig,1);          //启动日志监控
}
